package cn.xmall.validators;

import cn.xmall.models.Order;
import cn.xmall.models.OrderItem;
import cn.xmall.models.OrderShipping;
import cn.xmall.vo.IntegratedItemOrderVO;
import org.springframework.util.Assert;
import org.springframework.validation.Errors;
import org.springframework.validation.ValidationUtils;
import org.springframework.validation.Validator;

public class ItemOrderVoValidator implements Validator {

    private final Validator itemOrderItemValidator;
    private final Validator itemOrderShippingValidator;
    private final Validator itemOrderValidator;

    public ItemOrderVoValidator(Validator itemOrderValidator, Validator itemOrderItemValidator,
                                Validator itemOrderShippingValidator) {
        Assert.notNull(itemOrderItemValidator);
        Assert.notNull(itemOrderShippingValidator);
        Assert.notNull(itemOrderValidator);

        if(!itemOrderValidator.supports(Order.class)){
            throw new IllegalArgumentException("The supplied [Validator] must " +
                    "support the validation of [Order] instances.");
        }

        if(!itemOrderItemValidator.supports(OrderItem.class)){
            throw new IllegalArgumentException("The supplied [Validator] must " +
                    "support the validation of [OrderItem] instances.");
        }

        if(!itemOrderShippingValidator.supports(OrderShipping.class)){
            throw new IllegalArgumentException("The supplied [Validator] must " +
                    "support the validation of [OrderShipping] instances.");
        }

        this.itemOrderValidator=itemOrderValidator;
        this.itemOrderItemValidator = itemOrderItemValidator;
        this.itemOrderShippingValidator = itemOrderShippingValidator;
    }

    @Override
    public boolean supports(Class<?> clazz) {
        return IntegratedItemOrderVO.class.equals(clazz);
    }

    @Override
    public void validate(Object target, Errors errors) {
       ValidationUtils.rejectIfEmpty(errors,"orderItems",null,
               "orderItems is empty");
       ValidationUtils.rejectIfEmpty(errors,"orderShipping",null,
               "orderShipping is empty");
       try{
            IntegratedItemOrderVO vo=(IntegratedItemOrderVO) target;
            errors.pushNestedPath("itemOrderItem");
            for(OrderItem orderItem:vo.getOrderItems()){
                ValidationUtils.invokeValidator(this.itemOrderItemValidator,orderItem,errors);
            }
            errors.popNestedPath();
            errors.pushNestedPath("itemOrderShipping");
            ValidationUtils.invokeValidator(this.itemOrderShippingValidator,vo.getOrderShipping(),errors);
            errors.popNestedPath();
            errors.pushNestedPath("itemOrder");
            Order order=(Order) target;
            ValidationUtils.invokeValidator(this.itemOrderValidator,order,errors);
       }finally {
           errors.popNestedPath();
       }
    }
}
